package com.enjoyor.soa.traffic.server.tsms.handler;

import com.enjoyor.soa.traffic.core.tsms.domain.RouteInfo;
import com.enjoyor.soa.traffic.core.tsms.domain.RoutePoint;
import com.enjoyor.soa.traffic.core.tsms.domain.TaskExecuteRecord;
import com.enjoyor.soa.traffic.core.tsms.enums.EnumDicPublic;
import com.enjoyor.soa.traffic.server.tsms.common.RehearseGlobal;
import com.enjoyor.soa.traffic.server.tsms.helper.RouteClashHelper;
import com.enjoyor.soa.traffic.server.tsms.helper.RouteHandleHelper;
import com.enjoyor.soa.traffic.util.handler.BasicMsgHandler;
import com.enjoyor.soa.traffic.util.helper.TimeHelper;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

/**
 * 接收数据，数据清理
 */
public class ClashPrognosisHandler extends BasicMsgHandler<String> {
	private int routeSplitTime = 1000;//线路拆分间隔
	private int timeNum = 30;//冲突校验的时间间隔数
	private int clashDistance = 200;//车队冲突距离

	private ClashPrognosisHandler() {
		super(1000,"预测冲突");
	}

	private static ClashPrognosisHandler single;

	public static ClashPrognosisHandler getInstance() {
		if (single == null) {
			synchronized (ClashPrognosisHandler.class) {
				if (single == null) {
					single = new ClashPrognosisHandler();
					single.setMultiProcess(2, 20, 5);
				}
			}
		}
		return single;
	}


	@Override
	protected boolean task(int taskTimes){
        return true;
    }
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	protected boolean process(String executeTaskIdMsg) {
		try {
			//String executeTaskIdMsg = msg.getExecuteTaskId();
			List<Map<String, Object>> taskRouteList = new ArrayList<Map<String, Object>>();
			String beginTime = TimeHelper.dateToLongString();//执行开始时间
			long minBeginLong = TimeHelper.StringToDateTime(beginTime, "yyyy-MM-dd HH:mm:ss");//开始时间转化为时间戳
			long maxEndLong = 0;//最大结束时间戳
			//List<Map<String, String>> expectEndTimeList = new ArrayList<Map<String, String>>();//存储所有执行任务的预计结束时间
			//获取所有执行线路数据
			for (String key : RehearseGlobal.ActionDataPool.keySet()) {
				Map<String, Object> actionDataMap = RehearseGlobal.ActionDataPool.get(key);
				if(actionDataMap != null  && !actionDataMap.isEmpty()) {
					List<RouteInfo> routeInfoList = (List<RouteInfo>)actionDataMap.get("routeInfoList");
					boolean isDeviateCoord = (boolean)actionDataMap.get("isDeviateCoord");
					if(routeInfoList != null && routeInfoList.size() > 0 && !isDeviateCoord) {
						String taskId = (String)actionDataMap.get("taskId");
						String taskName = (String)actionDataMap.get("taskName");
						String executeTaskId = (String)actionDataMap.get("executeTaskId");
						Map<String, Object> lastGeo = (Map<String, Object>)actionDataMap.get("lastGeo");
						RouteInfo routeInfo = routeInfoList.get(0);
						List<RoutePoint> routePointList = routeInfo.getRoutePointList();
						if(routePointList.size() > 0) {
							double startLength = (double) lastGeo.get("distanceStartPointLength");//距起点长度
							//获取上一个途径点序号
							int iPoint = RouteHandleHelper.getRoutePointNum(routePointList, startLength);
							if(iPoint >= routePointList.size()-1 || iPoint < 0) {//途径点序号小于起点或者大于终点，舍弃
								continue;
							}
							//下一个途径点相关信息
							String nextLeaveTime = beginTime.split(" ")[0] + " " +routePointList.get(iPoint+1).getPlanTime() + ":00";
							int nextPointLength = routePointList.get(iPoint+1).getPointLength().intValue();
							double nextParkTime = routePointList.get(iPoint+1).getParkTime();
							long nextParkTimeL = (long)nextParkTime*60*1000;//停留时间转化为毫秒
							long nextLeaveTimeL = TimeHelper.StringToDateTime(nextLeaveTime, "yyyy-MM-dd HH:mm:ss");//下个途径点离开时间戳
							long nextArriveTimeL = nextLeaveTimeL - nextParkTimeL;//下个途径点到达时间戳
							double speed = routePointList.get(iPoint+1).getSpeed();
							double nextTime = (nextPointLength - startLength)/(speed * 1000 / 3600); //到下个途径点所需时间（单位为秒）
							//终点相关信息
							String endPointTime = beginTime.split(" ")[0] + " " +routePointList.get(routePointList.size()-1).getPlanTime() + ":00";
							long endPointTimeL = TimeHelper.StringToDateTime(endPointTime, "yyyy-MM-dd HH:mm:ss");//终点时间戳
							long endNeedTime = endPointTimeL - nextArriveTimeL + (long)nextTime;//预计到达终点所需时间
							long endLong = minBeginLong + endNeedTime;
							String endTime = TimeHelper.dateToLongString(new Date(endLong));//预计结束时间
							maxEndLong = Math.max(endLong, maxEndLong);//取结束时间最大值

							Map<String, Object> routeMap = new HashMap<String, Object>();
							routeMap.put("taskId", taskId);
							routeMap.put("taskName", taskName);
							routeMap.put("routeInfo", routeInfo);
							routeMap.put("beginTime", beginTime);
							routeMap.put("endTime", endTime);
							routeMap.put("startLength", startLength);
							taskRouteList.add(routeMap);

							com.alibaba.fastjson.JSONObject jsonObject = new com.alibaba.fastjson.JSONObject();
							//记录任务的预计结束时间
							Map<String, String> expectEndTimeMap = new HashMap<String, String>();
							expectEndTimeMap.put("type", "expectEndTime");
							//expectEndTimeMap.put("recordTime", TimeHelper.dateToLongString());
							expectEndTimeMap.put("content", endTime);
							expectEndTimeMap.put("endTime", endTime);
							jsonObject.put(RehearseGlobal.ActionDataPool.get(executeTaskId).get("routeId").toString(), expectEndTimeMap);
							InitializeHandler.getInstance().getServerPushServiceImpl().pushMessage("" + executeTaskIdMsg, jsonObject);
						}
					}

				}
			}

			Map<String, Map<String, Object>> clashMap = new HashMap<String, Map<String, Object>>();
			if(taskRouteList != null && taskRouteList.size() > 0) {
				//执行线路按规定时间间隔进行拆分
				//Map<String, Map<String, Map>> taskByTimeMap = RouteHandleHelper.routeInfoByTime(taskRouteList, routeSplitTime, true);
				Map<String, Map<String, Map>> taskByTimeMap = new HashMap<String, Map<String,Map>>();
				Vector<Thread> ts = new Vector<Thread>();
				for (Map<String, Object> taskRouteMapTemp : taskRouteList) {
					Thread t = new Thread(new Runnable() {
						@Override
						public void run() {
							RouteHandleHelper.routeInfoByTimeOne(taskByTimeMap, taskRouteMapTemp, routeSplitTime, true);
						}
					});
					ts.add(t);
					t.start();
				}
				for (Thread t : ts) {
					try {
						t.join();//等待所有线路拆分完成
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				
				if(taskByTimeMap != null && !taskByTimeMap.isEmpty()) {
					//根据线路分隔数据分析冲突情况
					clashMap =  RouteClashHelper.routeClashAnalysis(taskByTimeMap, taskRouteList, minBeginLong, maxEndLong,
							routeSplitTime, timeNum, clashDistance, true);
				}
			}

			boolean isClash = false;
			List<Map<String, Object>> clashInfoList = new ArrayList<Map<String, Object>>();
			if(clashMap != null && !clashMap.isEmpty()) {
				isClash = true;
				for (Map.Entry<String, Map<String, Object>> m : clashMap.entrySet()) {
					Map<String, Object> clashInfoMap = RouteClashHelper.getClashInfoByChange(m.getValue());
					clashInfoMap.put("clashId", m.getKey());
					clashInfoList.add(clashInfoMap);
				}
				//clashInfoList排序(根据冲突ID后面的时间戳);
				Collections.sort(clashInfoList, new Comparator<Map<String, Object>>() {
					/*
					 * int compare(Person p1, Person p2) 返回一个基本类型的整型， 返回负数表示：p1
					 * 小于p2， 返回0 表示：p1和p2相等， 返回正数表示：p1大于p2
					 */
					@Override
					public int compare(Map<String, Object> p1, Map<String, Object> p2) {
						String clashId1= ((String)p1.get("clashId")).split("_")[1];
						String clashId2= ((String)p2.get("clashId")).split("_")[1];
						if (Long.parseLong(clashId1) > Long.parseLong(clashId2)) {
							return 1;
						}
						if (Long.parseLong(clashId1) == Long.parseLong(clashId2)) {
							return 0;
						}
						return -1;
					}

				});
			}
			String isWarn = "0";
			String content = "预测执行情况正常。";
			String recordTypeId = EnumDicPublic.INFO_EXPECT_EXECUTE.getKey();
			String recordTypeName = EnumDicPublic.INFO_EXPECT_EXECUTE.getValue();
			if(isClash) {
				isWarn = "1";
				content = "预测执行情况存在冲突!";
				recordTypeId = EnumDicPublic.WRAN_EXPECT_CLASH.getKey();
				recordTypeName = EnumDicPublic.WRAN_EXPECT_CLASH.getValue();
			}
			com.alibaba.fastjson.JSONObject jsonObject = new com.alibaba.fastjson.JSONObject();
			Map<String, Object> expectClashMap = new HashMap<String, Object>();
			expectClashMap.put("type", "expect");
			expectClashMap.put("isClash", isClash);
			expectClashMap.put("recordTime", TimeHelper.dateToLongString());
			expectClashMap.put("content", content);
			expectClashMap.put("clashContent", clashInfoList);
			//expectClashMap.put("expectEndTime", expectEndTimeList);
			jsonObject.put(RehearseGlobal.ActionDataPool.get(executeTaskIdMsg).get("routeId").toString(), expectClashMap);
			InitializeHandler.getInstance().getServerPushServiceImpl().pushMessage("" + executeTaskIdMsg, jsonObject);
			
			//记录预测信息
			TaskExecuteRecord taskExecuteRecord = new TaskExecuteRecord();
			taskExecuteRecord.setExecuteTaskId(executeTaskIdMsg);
			taskExecuteRecord.setIsWarn(isWarn);
			taskExecuteRecord.setRecordTypeId(recordTypeId);
			taskExecuteRecord.setRecordTypeName(recordTypeName);
			taskExecuteRecord.setRecordContent(content);
			InitializeHandler.getInstance().getTaskExecuteRecordService().insertRecord(taskExecuteRecord, "预测执行情况");
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return true;
	}
}
